package com.itheima.d2_xml;

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.util.List;

/**
 * 目标：掌握使用Dom4j框架解析XML文件。
 *
 *  XML（ 全称EXtensible Markup Language， 可扩展标记语言 ）
 *      本质是一种数据的格式，可以用来存储复杂的数据结构，和数据关系。
 *      应用场景：经常用来做为系统的配置文件；或者作为一种特殊的数据结构，在网络中进行传输。
 *
 * XML的特点:
 * XML中的“<标签名>” 称为一个标签或一个元素，一般是成对出现的。
 * XML中的标签名可以自己定义（可扩展），但必须要正确的嵌套。
 * XML中只能有一个根标签。
 * XML中的标签可以有属性。属性是由键和值组成的
 * 如果一个文件中放置的是XML格式的数据，这个文件就是XML文件，后缀一般要写成.xml。
 *
 * XML的创建:
 * 就是创建一个XML类型的文件，要求文件的后缀必须使用xml，如hello_world.xml
 * xml文件是可以在浏览器中直接渲染出来的
 *
 * XML的语法规则:
 *      XML文件的后缀名为：xml，文档声明必须是第一行（也叫抬头声明）
 *          <?xml version="1.0" encoding="UTF-8" ?>
 *          version：XML默认的版本号码、该属性是必须存在的
 *          encoding：本XML文件的编码
 *      XML中可以定义注释信息：<!–- 注释内容 -->
 *      XML中书写”<”、“&”等，可能会出现冲突，导致报错，此时可以用如下特殊字符替代。
 *          &lt;    <  小于
 *          &gt;    >  大于
 *          &amp;   &  号
 *          &apos;  '  单号
 *          &quot;  "  引号
 *      XML中可以写一个叫CDATA的数据区: <![CDATA[   …内容…  ]]>，里面的内容可以随便写，特殊符号如<和大于号也不会报错
 *
 *  注意：程序员并不需要自己写原始的IO流代码来解析XML，难度较大！也相当繁琐！
 *  其实，有很多开源的，好用的，解析XML的框架，最知名的是：Dom4j(第三方研发的)
 *
 * 使用Dom4J解析出XML文件:
 *      需求：使用Dom4J把一个XML文件的数据进行解析
 * 步骤分析：
 *      下载Dom4j框架，官网下载。
 *      在项目中创建一个文件夹：lib
 *      将dom4j-2.1.3.jar文件复制到 lib 文件夹
 *      在jar文件上点右键，选择 Add as Library(意思是添加到依赖库) -> 点击OK
 *      在类中导包使用
 *
 * DOM4J解析XML文件的思想，文档对象模型：(是一种自上而下式的解析思想)
 *      1.SAXReader解析器可以把要解析的xml文件加载到内存中
 *      2.使用saxReader对象把需要解析的XML文件读成一个Document对象。这个文档对象可以代表整个xml文件，通过文档对象来访问 xml里面的所有数据
 *      3.然后通过文档对象去获取文档里面的Element对象：元素对象（也叫标签对象），可以获取xml文件中的根元素对象或者子元素对象
 *      4.接着可以通过元素对象获取元素的名字，还可以拿到 “Attribute:属性”对象，也可以拿到 “子元素、文本”
 *
 * Dom4j解析XML-得到Document对象
 *      SAXReader：Dom4j提供的解析器，可以认为是代表整个Dom4j框架
 *      SAXReader对象的构造器/方法：
 * public SAXReader()                       构建Dom4J的解析器对象
 * public Document read(String url)         把XML文件读成Document对象
 * public Document read(InputStream is)     通过字节输入流读取XML文件
 *
 *    Document对象的方法名：
 * Element getRootElement()                 获得根元素对象
 *
 *    Element对象提供的方法：
 * public String getName()                          得到元素名字
 * public List<Element> elements()                  得到当前元素下所有子元素
 * public List<Element> elements(String name)       得到当前元素下指定名字的子元素返回集合
 * public Element element(String name)              得到当前元素下指定名字的子元素,如果有很多名字相同的返回第一个
 * public String  attributeValue(String name)       通过属性名直接得到属性值
 * public String elementText(子元素名)               得到指定名称的子元素的文本
 * public String getText()                          得到文本
 *
 *
 * 按住ctrl+/键，可以快捷注释xml文件内容
 */
public class Dom4JTest1 {
    public static void main(String[] args) throws Exception {
        // 1、创建一个Dom4J框架提供的解析器对象
        SAXReader saxReader = new SAXReader();

        // 2、使用saxReader对象把需要解析的XML文件读成一个Document对象。这个文档对象可以代表整个xml文件
        Document document =
                saxReader.read("Day10Properties-Xml-Log-App\\src\\helloworld.xml");

        // 3、从文档对象中解析XML文件的全部数据了，获得根元素对象
        Element root = document.getRootElement();   //可以拿到<users>根元素，也就是根标签
        System.out.println(root.getName());

        System.out.println("--------------用根元素对象获取根元素下的，指定名字user的全部一级子元素--------");

        // 4、获取根元素下的全部一级子元素。
        // List<Element> elements = root.elements();
        List<Element> elements = root.elements("user");
        for (Element element : elements) {
            System.out.println(element.getName());
        }

        System.out.println("--------------用根元素对象得到指定名字people的子元素,如果有很多名字相同的返回第一个--------------------");

        // 5、获取当前元素下的某个子元素。 public String getText()  得到文本
        Element people = root.element("people");
        System.out.println(people.getText());

        // 如果下面有很多子元素user，默认获取第一个。  public String elementText(子元素名) 得到指定名称的子元素的文本
        Element user = root.element("user");
        System.out.println(user.elementText("name"));

        System.out.println("-------利用获取到的子元素对象，再通过子元素对象指定属性名直接得到属性值--------");

        // 6、获取元素的属性信息呢？public String  attributeValue(String name)  通过属性名直接得到属性值
        System.out.println(user.attributeValue("id"));
        //也可以先拿到“id”的属性对象
        Attribute id = user.attribute("id");
        System.out.println(id.getName());
        System.out.println(id.getValue());

        //假设xml文件里面的属性很多，其实我看磊哥写之前也不确定自己记得有这个方法
        List<Attribute> attributes = user.attributes();
        for (Attribute attribute : attributes) {
            System.out.println(attribute.getName() + "=" + attribute.getValue());
        }

        // 7、如何获取全部的文本内容:获取当前元素下的子元素文本值
        //方法一：用获取到的子元素对象，调用elementText获取该子元素下面，指定名称的子元素的文本内容
        System.out.println(user.elementText("name"));
        System.out.println(user.elementText("地址"));
        // 取出文本去除前后空格
        System.out.println(user.elementTextTrim("地址"));
        System.out.println(user.elementText("password"));

        System.out.println("--------------------");

        //方法二：把user看做根元素去调用element方法，然后获得指定名字的子元素，再用子元素去获取文本内容
        Element data = user.element("data");
        System.out.println(data.getText());
        //上面取出来的结果 3 < 2 && 5 > 4 开头有空格，去前后空格方法：
        System.out.println(data.getTextTrim()); // 取出文本去除前后空格
    }
}
